﻿using AutoMapper;
using Dm.filter.log;
using IdentityModel;
using Lazy.Captcha.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using Panda.DynamicWebApi;
using Panda.DynamicWebApi.Attributes;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using WareHose.Application.Admins.Dto;
using WareHouse.Domain;
using WareHouse.Repositories;
using WareHose.Application.Paging;
using Microsoft.EntityFrameworkCore;
using System.Reflection;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Mysqlx.Crud;
using System.Drawing;
using System.Security.Policy;
using SqlSugar;
using WareHouse.DB.AllDbContext;
using Kdbndp;
using System.Security.Cryptography;
using CSRedis;

namespace WareHose.Application.Admins
{
    [DynamicWebApi]
    [ApiExplorerSettings(GroupName = "v1")]
    //[Authorize]
    public class AdminService : IAdminService, IDynamicWebApi
    {
        private readonly IBaseRepository<Admin> admines;
        //private readonly IBaseRepository<Department> departmentt;
        //private readonly IBaseRepository<Role> rolee;

        private readonly IMapper mapper;
        private readonly IHttpContextAccessor httpContextAccessor;
        private readonly IConfiguration configuration;
        private readonly ICaptcha _captcha;
        private readonly SqlSugarDbContext _db;
        //sqlsuagr
        private readonly ISqlSugarClient SugarClient;
        private readonly CSRedisClient redis;




        //private readonly SqlSugarClient db;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="admines"></param>
        /// <param name="mapper"></param>
        public AdminService(IBaseRepository<Admin> admines, IMapper mapper, IHttpContextAccessor httpContextAccessor,
            IConfiguration configuration, ICaptcha captcha, SqlSugarDbContext _db, ISqlSugarClient SugarClient)
        {
            this.SugarClient = SugarClient;
            //this.db = db;

            this.admines = admines;
            this.mapper = mapper;
            this.httpContextAccessor = httpContextAccessor;
            this.configuration = configuration;
            _captcha = captcha;
            this._db = _db;
            redis = new CSRedisClient("127.0.0.1:6379");
        }

        /// <summary>
        /// sqlsugar迁移
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public string Index()
        {
            return "success";
        }

        /// <summary>
        /// 验证码
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public string Captcha()
        {
            redis.Del("Captcha");
            string guid = $"captcha:{Guid.NewGuid().ToString("N")}";
            var info = _captcha.Generate(guid);
            redis.Set("Captcha", info.Code);
            httpContextAccessor.HttpContext.Response.Cookies.Append("ValidateCode", guid);
            var stream = new MemoryStream(info.Bytes);
            return Convert.ToBase64String(stream.ToArray());
        }


        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="addOrUpdAdminDto"></param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task<ResultDto> AddUpdAsync(AddOrUpdAdminDto addOrUpdAdminDto)
        {
            try
            {
                var admin = await admines.FistAsync(m => m.UserName == addOrUpdAdminDto.UserName);
                if (admin != null)
                {
                    return new ResultDto { Code = Status.Failed, Message = "用户名已存在" };
                }
                else
                {
                    var entity = mapper.Map<AddOrUpdAdminDto, Admin>(addOrUpdAdminDto);
                    entity.Password = entity.Password.Md5();
                    await admines.InsertAsync(entity);
                    return new ResultDto { Code = Status.Success, Message = "添加成功" };
                }
            }
            catch (Exception e)
            {
                return new ResultDto { Code = Status.Failed, Message = e.Message };
            }
        }
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="loginDto"></param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task<ResultDto<LoginData>> LoginAsync(LoginDto loginDto)
        {
            try
            {
                var admin = await admines.FistAsync(m => m.UserName == loginDto.UserName);
                if (admin == null)
                {
                    return new ResultDto<LoginData> { Code = Status.Failed, Message = "用户名不存在" };
                }
                else
                {
                    if (admin.Password != loginDto.Password.Md5())
                    {
                        return new ResultDto<LoginData> { Code = Status.Failed, Message = "密码错误" };
                    }
                    else
                    {
                        var Yam = redis.Get("Captcha");
                        if (Yam.ToLower() == loginDto.captchaCode.ToLower())
                        {
                            //更新末次登录IP和末次登录时间
                            admin.LastLoginIp = httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
                            admin.LastLoginTime = DateTime.Now;
                            await admines.UpdateAsync(admin);

                            DateTime expires;
                            //调用生成Token方法
                            var authInfo = GenerateToken(admin, out expires);

                            return new ResultDto<LoginData>
                            {
                                Code = Status.Success,
                                Data = new LoginData
                                {
                                    AccessToken = authInfo,
                                    TokenType = "Bearer",
                                    expires = expires
                                },
                                Message="登录成功"
                            };

                            //return new ResultDto<LoginData> { Code = Status.Success, Message = "登录成功！", Data = authInfo };
                        }
                        else
                        {
                            return new ResultDto<LoginData>
                            {
                                Code = Status.Failed,
                                Message="验证码错误"
                            };
                        }
                           
                    }
                }
            }
            catch (Exception e)
            {
                return new ResultDto<LoginData> { Code = Status.Failed, Message = e.Message };
            }
        }

        /// <summary>
        /// JTW方法
        /// </summary>
        /// <param name="admin"></param>
        /// <returns></returns>
        private string GenerateToken(Admin admin, out DateTime expires)
        {
            IList<Claim> claims = new List<Claim> {
                                new Claim(JwtClaimTypes.Id, admin.AdminId.ToString()),
                                new Claim(JwtClaimTypes.Name, admin.UserName)
                            };

            //JWT密钥
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtConfig:Bearer:SecurityKey"]));

            //算法
            var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            //过期时间
            expires = DateTime.UtcNow.AddHours(30);

            //Payload负载
            var token = new JwtSecurityToken(
                issuer: configuration["JwtConfig:Bearer:Issuer"],
                audience: configuration["JwtConfig:Bearer:Audience"],
                claims: claims,
                notBefore: DateTime.UtcNow,
                expires: expires,
                signingCredentials: cred
                );

            var handler = new JwtSecurityTokenHandler();

            //生成令牌
            string jwt = handler.WriteToken(token);

            return jwt;
        }

        /// <summary>
        /// 角色
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public async Task<ResultDto<PermissionDto>> Info()
        {
            return new ResultDto<PermissionDto>
            {
                Code = Status.Success,
                Data = new PermissionDto
                {
                    roles = new string[] { "ADMIN" },
                    userId = 1773894558216753152,
                    username = "admin",
                    nickname = "系统管理员",
                    avatar = "https://oss.youlai.tech/youlai-boot/2023/05/16/811270ef31f548af9cffc026dfc3777b.gif",
                    perms = new string[]
                    {
                       "sys:menu:delete",
                       "sys:dept:edit",
                       "sys:dict_type:add",
                       "sys:dict:edit",
                       "sys:dict:delete",
                       "sys:dict_type:edit",
                       "sys:menu:add",
                       "sys:user:add",
                       "sys:role:edit",
                       "sys:dept:delete",
                       "sys:user:password_reset",
                       "sys:user:edit",
                       "sys:user:delete",
                       "sys:dept:add",
                       "sys:role:delete",
                       "sys:dict_type:delete",
                       "sys:menu:edit",
                       "sys:dict:add",
                       "sys:role:add"
                    }

                }
            };
        }


        /// <summary>
        /// 显示员工
        /// </summary>
        /// <param name="UserName"></param>
        /// <param name="Job"></param>
        /// <param name="DeparementId"></param>
        /// <param name="RoleId"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultDtos<List<AddOrUpdAdminDto>>> AdminPage(string UserName, int? Job, int? DeparementId, int? RoleId, int pageIndex = 1, int pageSize = 4)
        {
            RefAsync<int> total = 0;
            RefAsync<int> totalPage = 0;
            var list = await SugarClient.Queryable<Admin>()
               .InnerJoin<Department>((a, b) => a.DeparementId == b.Did)
               .InnerJoin<Role>((a, b, c) => a.RoleId == c.RoleId)
               .Select((a, b, c) => new AddOrUpdAdminDto
               {
                   AdminId = a.AdminId,
                   UserName = a.UserName,
                   Password = "****",
                   Job = a.Job,
                   TureName = a.TureName,
                   Email = a.Email,
                   Phone = a.Phone,
                   Phones = a.Phones,
                   DeparementId = b.Did,
                   DName = b.DName,
                   RoleId=c.RoleId,
                   RName=c.RoleName,
               })
             .WhereIF(!string.IsNullOrEmpty(UserName), a => a.UserName.Equals(UserName))
                     .WhereIF(Job != null, a => a.Job == Job)
                     .WhereIF(DeparementId != null, a => a.DeparementId == DeparementId)
                     .WhereIF(RoleId != null, a => a.RoleId == RoleId)
                    .ToPageListAsync(pageIndex, pageSize, total, totalPage);
            return new ResultDtos<List<AddOrUpdAdminDto>>
            {
                Code = Status.Success,
                Data = list,
                Listcount = list.Count,
            };
        }




        /// <summary>
        /// 用户删除
        /// </summary>
        /// <param name="AdminId"></param>
        /// <returns></returns>
        [HttpDelete]

        public async Task<ResultDto> AdminDelete(string AdminId)
        {
            if (AdminId != null)
            {
                string[] ids = AdminId.Split(',');
                foreach (var item in ids)
                {
                    await admines.DeleAsync(Convert.ToInt64(item));
                }
                return new ResultDto { Code = Status.Success, Message = "删除成功" };
            }
            else
            {
                return new ResultDto { Code = Status.Success, Message = "删除失败" };
            }

        }
    }
}
